/*
 * @Author: xiaosihan
 * @Date: 2023-05-30 15:24:40
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-05-06 02:06:23
 */

import FabricCanvas from '@/myFabric/FabricCanvas';
import fontManage from '@/myFabric/fontManage';
import { fabric } from 'fabric';
import { clone, cloneDeep, get } from 'lodash';
import { Texture, SRGBColorSpace } from 'three';
import threeLoader from 'three-base/threeLoader';
import designEditor from './designEditor';

// 纹理管理器
class TextureManager {
  constructor() { }

  //div容器元素
  divDom = (() => {
    const divDom = document.createElement('div');
    divDom.style.width = '1024px';
    divDom.style.height = '1024px';
    return divDom;
  })();

  // 画布
  canvas = (() => {
    const canvas = document.createElement('canvas');
    canvas.width = 1024;
    canvas.height = 1024;
    this.divDom.append(canvas);
    return canvas;
  })();

  // fabric 编辑器
  fabricCanvas = (() => {
    const fabricCanvas = new FabricCanvas(this.canvas);
    fabricCanvas.selection = true;
    // fabricCanvas.on("before:render", (e) => {
    //     this.background.render(fabricCanvas.getContext());
    // });
    return fabricCanvas;
  })();

  // 画布
  canvasMap: Map<string, HTMLCanvasElement> = new Map();
  // 透明画布
  transparentCanvasMap: Map<string, HTMLCanvasElement> = new Map();
  // 纹理
  textureMap: Map<string, Texture> = new Map();
  // 透明的纹理
  transparentTextureMap: Map<string, Texture> = new Map();

  // 重置纹理
  async init(design_datas: { [key: string]: Object }) {
    this.canvasMap.clear();
    this.transparentCanvasMap.clear();
    this.textureMap.clear();
    this.transparentTextureMap.clear();

    for (let name in design_datas) {
      const canvas = document.createElement('canvas');
      const transparentCanvas = document.createElement('canvas');
      transparentCanvas.width = canvas.width = 1024;
      transparentCanvas.height = canvas.height = 1024;
      // canvas.style.width = '100px';
      // canvas.style.height = '100px';
      // canvas.style.border = '1px solid #cccccc';
      // document.body.append(canvas);
      const ctx = canvas.getContext('2d')!;
      ctx.clearRect(0, 0, 1024, 1024);
      this.canvasMap.set(name, canvas);
      this.transparentCanvasMap.set(name, transparentCanvas);
      const texture = threeLoader.getTexture(canvas);
      const transparentTexture = threeLoader.getTexture(transparentCanvas);

      texture.colorSpace = SRGBColorSpace;
      texture.name = '带背景的纹理';
      transparentTexture.colorSpace = SRGBColorSpace;
      transparentTexture.name = '不带背景的纹理';

      texture.flipY = false; //翻转纹理
      transparentTexture.flipY = false; //翻转纹理

      this.textureMap.set(name, texture);
      this.transparentTextureMap.set(name, transparentTexture);

      await new Promise<void>(async (resolve, reject) => {
        const objects: Array<any> = get(design_datas, ['name', 'objects']) || [];
        // 加载用到的字体
        await fontManage.loadFont(objects.map((o) => o.fontFamily));

        const background = (design_datas[name] as any).background;
        delete (design_datas[name] as any).background;

        this.fabricCanvas.loadFromJSON(design_datas[name], () => {
          this.dwragToCanvas(name, this.canvas);

          // 裁剪纹理
          const textCanvasCtx = this.getContext(name);
          const fabricMark = designEditor.fabricMarkMap.get(name);
          if (fabricMark && textCanvasCtx && texture) {
            fabricMark.clip(textCanvasCtx, 1024, 1);
          }

          //绘制背景颜色
          if (textCanvasCtx) {
            textCanvasCtx.save();
            textCanvasCtx.fillStyle = background || '#ffffff';
            textCanvasCtx.globalCompositeOperation = 'destination-over';
            textCanvasCtx.fillRect(0, 0, 1024, 1024);
            textCanvasCtx.restore();
            texture.needsUpdate = true;
          }

          // 还原原来的背景颜色
          (design_datas[name] as any).background = background;

          // 裁剪透明纹理纹理
          const transparentTextCanvasCtx = this.getTransparentContext(name);
          if (fabricMark && transparentTextCanvasCtx && texture) {
            fabricMark.clip(transparentTextCanvasCtx, 1024, 1);
          }

          resolve();
        });
      });
    }
  }

  //加载fabric数据,并更新纹理
  async updataTextByFabricJSON(name: string, fabricJson: any) {
    await new Promise<void>((resolve, reject) => {
      const newFabricJson = clone(fabricJson);
      const background = newFabricJson.background || "#ffffff";
      delete newFabricJson.background;
      this.fabricCanvas.loadFromJSON(newFabricJson, () => {
        const targetCanvas = this.canvasMap.get(name);
        if (targetCanvas) {
          const targetCtx = targetCanvas.getContext('2d')!;
          targetCtx.clearRect(0, 0, 1024, 1024);
          targetCtx.drawImage(
            this.canvas,
            0,
            0,
            this.canvas.width,
            this.canvas.height,
            0,
            0,
            1024,
            1024,
          );

          // //绘制背景颜色
          targetCtx.save();
          targetCtx.fillStyle = background || '#ffffff';
          targetCtx.globalCompositeOperation = 'destination-over';
          targetCtx.fillRect(0, 0, 1024, 1024);
          targetCtx.restore();

          const targetTexture = this.textureMap.get(name);
          if (targetTexture) {
            targetTexture.needsUpdate = true;
          }
        }
        // 更新透明纹理
        const transparentTargetCtx = this.getTransparentContext(name);
        if (transparentTargetCtx) {
          transparentTargetCtx.clearRect(0, 0, 1024, 1024);
          transparentTargetCtx.drawImage(
            this.canvas,
            0,
            0,
            this.canvas.width,
            this.canvas.height,
            0,
            0,
            1024,
            1024,
          );
        }
        const tansparentTargetTexture = this.transparentTextureMap.get(name);
        if (tansparentTargetTexture) {
          tansparentTargetTexture.needsUpdate = true;
        }

        resolve();
      });
    });
  }

  // 把图像绘制到canvas上 并更新纹理对象
  dwragToCanvas(name: string, canvas: HTMLCanvasElement, designMark?: HTMLImageElement) {
    const targetCanvas = this.canvasMap.get(name);
    if (targetCanvas) {
      const targetCtx = targetCanvas.getContext('2d')!;
      targetCtx.clearRect(0, 0, 1024, 1024);
      targetCtx.drawImage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, 1024, 1024);

      if (designMark) {
        targetCtx.save();
        targetCtx.globalCompositeOperation = "destination-out";
        targetCtx.globalAlpha = 1;
        targetCtx.drawImage(designMark, 0, 0, 1024, 1024);
        targetCtx.restore();
      }
    }

    const targetTexture = this.textureMap.get(name);
    if (targetTexture) {
      targetTexture.needsUpdate = true;
    }

    // 绘制
    const targetTransparentCanvas = this.transparentCanvasMap.get(name);
    if (targetTransparentCanvas) {
      const targetCtx = targetTransparentCanvas.getContext('2d')!;
      targetCtx.clearRect(0, 0, 1024, 1024);
      targetCtx.drawImage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, 1024, 1024);

      if (designMark) {
        targetCtx.save();
        targetCtx.globalCompositeOperation = "destination-out";
        targetCtx.globalAlpha = 1;
        targetCtx.drawImage(designMark, 0, 0, 1024, 1024);
        targetCtx.restore();
      }

    }

    const targetTransparentTexture = this.transparentTextureMap.get(name);
    if (targetTransparentTexture) {
      targetTransparentTexture.needsUpdate = true;
    }
  }

  // 获取canvas
  getCanvas(name: string) {
    return this.canvasMap.get(name);
  }

  // 获取透明canvas
  getTansparentCanvas(name: string) {
    return this.transparentCanvasMap.get(name);
  }

  //获取canvas的上下文
  getContext(name: string) {
    const canvas = this.getCanvas(name);
    if (canvas) {
      return canvas.getContext('2d')!;
    } else {
      return undefined;
    }
  }

  //获取透明canvas的上下文
  getTransparentContext(name: string) {
    const canvas = this.getTansparentCanvas(name);
    if (canvas) {
      return canvas.getContext('2d')!;
    } else {
      return undefined;
    }
  }

  // 获取所有canvas
  getAllCanvas() {
    const canvas: { [key: string]: HTMLCanvasElement } = {};
    this.canvasMap.forEach((element, key) => {
      canvas[key] = element;
    });
    return canvas;
  }

  // 获取所有透明canvas
  getAllTansparentCanvas() {
    const canvas: { [key: string]: HTMLCanvasElement } = {};
    this.transparentCanvasMap.forEach((element, key) => {
      canvas[key] = element;
    });
    return canvas;
  }

  // 获取纹理
  getTexture(name: string) {
    return this.textureMap.get(name);
  }

  // 获取不带背景色的透明贴图
  getTransparentTexture(name: string) {
    return this.transparentTextureMap.get(name);
  }

  // 获取所有纹理
  getAllTexture() {
    const texture: { [key: string]: Texture } = {};

    this.textureMap.forEach((element, key) => {
      texture[key] = element;
    });

    return texture;
  }
}

const textureManager = (window.textureManager = new TextureManager());

export default textureManager;
